package com.kuaiyin.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.kuaiyin.exception.BaseException;
import net.datafaker.Faker;

import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * JSON 变量提取和转换工具类
 * 提供 JSON 字符串、JsonNode 和 Map 之间的相互转换功能
 */
public class JsonVariableExtractorUtils {
    // 变量匹配模式（如 {{variable}} 或 {{$function}}）
    private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{\\{(\\$?)(.+?)}}");

    // Faker 实例
    private static final Faker faker = new Faker(new Locale("zh-CN"));

    // Jackson 对象映射器（线程安全）
    private static final ObjectMapper objectMapper = new ObjectMapper();

    // 注册的函数处理器
    private static final Map<String, Function<String, Object>> functionHandlers = new HashMap<>();

    static {
        // 注册内置函数
        registerFunction("timestamp", input -> System.currentTimeMillis()); // 当前时间戳
        registerFunction("uuid", input -> UUID.randomUUID().toString());   // 随机UUID
        registerFunction("phone",input -> faker.phoneNumber().cellPhone());  // 随机 手机号码
        registerFunction("name", input -> faker.name().fullName());  // 随机名字
        registerFunction("randomInt", input -> faker.number().numberBetween(1, 1000001)); // 随机数字
        registerFunction("alphanumeric", input -> faker.regexify("[A-Za-z0-9]{8}"));    // 8位字母数字组合
    }

    /* ==================== 核心公共方法 ==================== */

    /**
     * 将任意 JSON 兼容对象转换为 Map
     * @param JSON 输入对象（JsonNode 或 JSON 字符串）
     * @return 转换后的 Map 结构
     * @throws IllegalArgumentException 如果输入类型不支持
     * @throws RuntimeException 如果 JSON 解析失败
     */
    public static Map<String, Object> toMap(Object JSON) {
        try {
            JsonNode node;

            if (JSON instanceof JsonNode) {
                node = (JsonNode) JSON;
            } else if (JSON instanceof String) {
                node = stringToJsonNode((String) JSON);
            } else {
                throw new IllegalArgumentException("输入必须是JsonNode或JSON字符串");
            }

            return objectMapper.convertValue(node, new TypeReference<Map<String, Object>>() {});
        } catch (Exception e) {
            throw new RuntimeException("JSON转换失败: " + e.getMessage(), e);
        }
    }

    /**
     * 安全转换方法（不抛出异常）
     * @param input 输入对象
     * @return 转换结果，失败返回空Map
     */
    public static Map<String, Object> toMapSafely(Object input) {
        try {
            return toMap(input);
        } catch (Exception e) {
            return Collections.emptyMap();
        }
    }

    /**
     * 将 JSON 字符串转换为 JsonNode
     * @param jsonString 合法的 JSON 字符串
     * @return JsonNode 对象
     * @throws JsonProcessingException 如果 JSON 格式无效
     */
    public static JsonNode stringToJsonNode(String jsonString) throws JsonProcessingException {
        try {
            return objectMapper.readTree(jsonString);
        } catch (JsonProcessingException e) {
            throw BaseException.of(0, "JSON格式无效", e);
        }
    }

    /**
     * 将 JsonNode 转换为 JSON 字符串
     * @param jsonNode JsonNode 对象
     * @return JSON 字符串
     * @throws JsonProcessingException 如果转换失败
     */
    public static String jsonNodeToString(JsonNode jsonNode) throws JsonProcessingException {
        return objectMapper.writeValueAsString(jsonNode);
    }

    /**
     * 将 Java 对象转换为 JSON 字符串
     * @param object 任意 Java 对象
     * @return JSON 字符串
     * @throws JsonProcessingException 如果转换失败
     */
    public static String objectToJsonString(Object object) throws JsonProcessingException {
        return objectMapper.writeValueAsString(object);
    }

    /**
     * 将 JSON 字符串转换为指定类型的 Java 对象
     * @param jsonString JSON 字符串
     * @param valueType 目标类型 Class 对象
     * @param <T> 泛型类型
     * @return 转换后的 Java 对象
     * @throws JsonProcessingException 如果转换失败
     */
    public static <T> T jsonStringToObject(String jsonString, Class<T> valueType) throws JsonProcessingException {
        return objectMapper.readValue(jsonString, valueType);
    }

    /**
     * 注册自定义函数处理器
     * @param functionName 函数名（不带 $ 前缀）
     * @param handler 函数处理逻辑
     */
    public static void registerFunction(String functionName, Function<String, Object> handler) {
        functionHandlers.put(functionName, handler);
    }

    /**
     * 提取 JSON 中的所有变量和函数调用
     * @param jsonString JSON 字符串
     * @return 包含所有变量/函数名的集合
     */
    public static Set<String> extractVariablesAndFunctions(String jsonString) {
        Set<String> variables = new HashSet<>();
        try {
            JsonNode jsonNode = stringToJsonNode(jsonString);
            extractFromNode(jsonNode, variables);
        } catch (Exception e) {
            extractFromString(jsonString, variables);
        }
        return variables;
    }

    /**
     * 替换 JSON 中的变量和函数
     * @param jsonString 原始 JSON 字符串
     * @param replacements 替换映射表（变量名 → 值）
     * @return 替换后的 JSON 字符串
     */
    public static String replaceVariablesAndFunctions(String jsonString, Map<String, Object> replacements) {
        try {
            JsonNode jsonNode = stringToJsonNode(jsonString);
            JsonNode replacedNode = replaceInNode(jsonNode, replacements);
            return jsonNodeToString(replacedNode);
        } catch (Exception e) {
            return replaceInString(jsonString, replacements);
        }
    }

    /**
     * 检查 JSON 是否包含变量或函数
     * @param jsonString JSON 字符串
     * @return 如果包含返回 true，否则 false
     */
    public static boolean containsVariablesOrFunctions(String jsonString) {
        return !extractVariablesAndFunctions(jsonString).isEmpty();
    }

    /* ==================== 私有工具方法 ==================== */

    /**
     * 递归遍历 JsonNode 提取变量
     * @param node 当前节点
     * @param variables 变量集合
     */
    private static void extractFromNode(JsonNode node, Set<String> variables) {
        if (node.isValueNode()) {
            extractFromString(node.asText(), variables);
        } else if (node.isObject()) {
            node.fields().forEachRemaining(entry -> extractFromNode(entry.getValue(), variables));
        } else if (node.isArray()) {
            node.forEach(element -> extractFromNode(element, variables));
        }
    }

    /**
     * 从字符串中提取变量
     * @param text 输入字符串
     * @param variables 变量集合
     */
    private static void extractFromString(String text, Set<String> variables) {
        Matcher matcher = VARIABLE_PATTERN.matcher(text);
        while (matcher.find()) {
            String isFunction = matcher.group(1);
            String name = matcher.group(2).trim();
            variables.add(!isFunction.isEmpty() ? "$" + name : name);
        }
    }

    /**
     * 递归替换 JsonNode 中的变量
     * @param node 当前节点
     * @param replacements 替换映射表
     * @return 替换后的新节点
     */
    private static JsonNode replaceInNode(JsonNode node, Map<String, Object> replacements) {
        if (node.isValueNode()) {
            String text = node.asText();
            return containsVariablesOrFunctions(text) ?
                    new TextNode(replaceInString(text, replacements)) :
                    node;
        } else if (node.isObject()) {
            ObjectNode newObjectNode = objectMapper.createObjectNode();
            node.fields().forEachRemaining(entry ->
                    newObjectNode.set(entry.getKey(), replaceInNode(entry.getValue(), replacements)));
            return newObjectNode;
        } else if (node.isArray()) {
            ArrayNode newArrayNode = objectMapper.createArrayNode();
            ((ArrayNode) node).forEach(element ->
                    newArrayNode.add(replaceInNode(element, replacements)));
            return newArrayNode;
        }
        return node;
    }

    /**
     * 替换字符串中的变量
     * @param text 原始字符串
     * @param replacements 替换映射表
     * @return 替换后的字符串
     */
    private static String replaceInString(String text, Map<String, Object> replacements) {
        StringBuilder result = new StringBuilder();
        Matcher matcher = VARIABLE_PATTERN.matcher(text);

        while (matcher.find()) {
            String isFunction = matcher.group(1);
            String name = matcher.group(2).trim();
            String replacementValue = !isFunction.isEmpty() ?
                    handleFunction(name) :
                    Optional.ofNullable(replacements.get(name)).map(Object::toString).orElse("");
            matcher.appendReplacement(result, replacementValue);
        }
        return matcher.appendTail(result).toString();
    }

    /**
     * 执行函数调用
     * @param functionName 函数名
     * @return 函数执行结果字符串
     */
    private static String handleFunction(String functionName) {
        return Optional.ofNullable(functionHandlers.get(functionName))
                .map(handler -> handler.apply(""))
                .map(Object::toString)
                .orElse("");
    }

    /* ==================== 测试用例 ==================== */

    public static void main(String[] args) {
        // 测试数据
        String jsonStr = "{\"authorization\":\"JWT {{name}}\",\"age\":30,\"address\":{\"city\":\"New York\"},\"tags\":[\"developer\",\"java\"],\"id\":\"{{$uuid}}\"}";

        // 测试变量提取
        Set<String> variables = extractVariablesAndFunctions(jsonStr);
        System.out.println("提取的变量: " + variables);

        // 测试变量替换
        Map<String, Object> replacements = new HashMap<>();
        replacements.put("name", "John Doe");
        String replacedJson = replaceVariablesAndFunctions(jsonStr, replacements);
        System.out.println("替换后的JSON:\n" + replacedJson);

        // 测试转换功能
        Map<String, Object> mapData = toMap(replacedJson);
        System.out.println("转换后的Map结构: " + mapData);
    }
}